﻿namespace HostTracker.Azure.Management

open System
open System.Text
open System.Net
open System.ServiceModel
open System.ServiceModel.Web
open System.Runtime.Serialization
open System.Xml.Serialization
open HostTracker.Azure.ProjectSettings
open HostTracker.Azure.Management.FSharpExtensions

type DeploymentSlot = Staging | Production
with 
    override x.ToString() = Reflection.unionToString typeof<DeploymentSlot> (fun x -> x.ToLower()) x
    static member Parse(str) = 
        Reflection.stringToUnion typeof<DeploymentSlot> (fun x -> x.ToLower()) str :?> DeploymentSlot

type DeploymentStatus = 
    | Running | Suspended | RunningTransitioning | SuspendedTransitioning 
    | Starting | Suspending | Deploying | Deleting 
with 
    override x.ToString() = Reflection.unionToStringPlain x
    static member Parse(str) = Reflection.stringToUnionPlain<DeploymentStatus> str

type InstanceStatus1 = 
    | Ready | Busy | Initializing | Stopping | Stopped | Unresponsive 
with 
    override x.ToString() = Reflection.unionToStringPlain x
    static member Parse(str) = Reflection.stringToUnionPlain<InstanceStatus1> str

// only for API version 2011-10-01 and later
type InstanceStatus2 = 
    | RoleStateUnknown | CreatingVM | StartingVM | CreatingRole | StartingRole | ReadyRole 
    | BusyRole | StoppingRole | StoppingVM | DeletingVM | StoppedVM | RestartingRole 
    | CyclingRole | FailedStartingVM | UnresponsiveRole 
with 
    override x.ToString() = Reflection.unionToStringPlain x
    static member Parse(str) = Reflection.stringToUnionPlain<InstanceStatus2> str
    
type InstanceStatus = Version1 of InstanceStatus1 | Version2 of InstanceStatus2
with 
    override x.ToString() =
        match x with
        | Version1 x -> x.ToString()
        | Version2 x -> x.ToString()
    static member Parse(str) = 
        try InstanceStatus2.Parse(str) |> Version2
        with _ ->
            try InstanceStatus1.Parse(str) |> Version1
            with _ -> reraise ()

type InstanceSize = 
    | ExtraSmall | Small | Medium | Large | ExtraLarge
with 
    override x.ToString() = Reflection.unionToStringPlain x
    static member Parse(str) = Reflection.stringToUnionPlain<InstanceSize> str

[<DataContract(Name = "CreateDeployment", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type DeploymentCreation(startImmediately: bool, treatWarnsAsError: bool) =
    let mutable name = ""
    let mutable packageUrl = ""
    let mutable label = ""
    let mutable config = ServiceConfiguration()
    [<DataMember(Name = "Name", Order = 1)>]
    member x.Name with get () = name and set v = name <- v
    [<DataMember(Name = "PackageUrl", Order = 2)>]
    member x.PackageUrl with get () = packageUrl and set v = packageUrl <- v
    [<DataMember(Name = "Label", Order = 3)>]
    member private x.LabelEncoded with get() = label and set v = label <- v
    member x.Label with get () = label.FromBase64() and set (v: string) = label <- v.ToBase64()
    [<DataMember(Name = "Configuration", Order = 4)>]
    member private x.ConfigEncoded with get () = config.ToString().ToBase64() and set (v: string) = config <- ServiceConfiguration.LoadFromString(v.FromBase64())
    //member x.ConfigString with get () = config.FromBase64() and set (v:string) = config <- v.ToBase64()
    member x.Config with get () = config and set v = config <- v
    //member x.ConfigBytes with get () = Convert.FromBase64String(config) and set v = config <- Convert.ToBase64String(v)
    [<DataMember(Name = "StartDeployment", Order = 5)>]
    member private x.IsStartedImmediately with get () = startImmediately and set _ = ()
    [<DataMember(Name = "TreatWarningsAsError", Order = 6)>]
    member private x.TreatWarnsAsError with get () = treatWarnsAsError and set _ = ()

(*
<?xml version="1.0" encoding="utf-8"?>
  <Deployment xmlns="http://schemas.microsoft.com/windowsazure">
    <Name>deployment-name</Name>
    <DeploymentSlot>current-deployment-environment</DeploymentSlot>
    <PrivateID>deployment-id<PrivateID>
    <Status>deployment-status</Status>
    <Label>base64-encoded-deployment-label</Label>
    <Url>deployment-url</Url>
    <Configuration>base-64-encoded-configuration-file</Configuration>
    <RoleInstanceList>
      <RoleInstance>
        <RoleName>role-name</RoleName>
        <InstanceName>role-instance-name</InstanceName>
        <InstanceStatus>instance-status</InstanceStatus>
        <InstanceUpgradeDomain>integer-identifying-the-upgrade-domain</InstanceUpgradeDomain>
        <InstanceFaultDomain>integer-identifying-the-fault-domain</InstanceFaultDomain>
        <InstanceSize>size-of-the-instance</InstanceSize>
        <InstanceStateDetails>snapshot-of-the-state-of-the-vm</InstanceStateDetails>
        <InstanceErrorCode>error-code</InstanceErrorCode>
      </RoleInstance>
    </RoleInstanceList>
    <UpgradeStatus>
       <UpgradeType>Auto|Manual</UpgradeType>
       <CurrentUpgradeDomainState>Before|During</CurrentUpgradeDomainState>
       <CurrentUpgradeDomain>n</CurrentUpgradeDomain>
    </UpgradeStatus>
    <UpgradeDomainCount>number-of-upgrade-domains-in-deployment</UpgradeDomainCount>
    <RoleList>
      <Role>
        <RoleName>role-name</RoleName>
        <OsVersion>operating-system-version</OsVersion>
      </Role>
    </RoleList>
    <SdkVersion>sdk-version-used-to-create-package</SdkVersion>
    <InputEndpointList>
        <InputEndpoint>
           <RoleName>role-name</RoleName>
           <Vip>virtual-ip-address</Vip>
           <Port>port-number</Port>
        </InputEndpoint>
        …
    </InputEndpointList>
   <Locked>deployment-write-allowed-status</Locked>
   <RollbackAllowed>rollback-operation-allowed</RollbackAllowed>
  </Deployment>
*)

[<DataContract(Name = "InputEndpoint", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type InputEndpoint() =
    let mutable roleName = ""
    let mutable vIp = ""
    let mutable port = 0
    [<DataMember(Name = "RoleName", Order = 1)>]
    member x.RoleName with get () = roleName and set v = roleName <- v
    [<DataMember(Name = "Vip", Order = 2)>]
    member x.Vip with get () = vIp and set v = vIp <- v
    [<DataMember(Name = "Port", Order = 3)>]
    member x.Port with get () = port and set v = port <- v

[<CollectionDataContract(Name = "InputEndpointList", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type InputEndpoints() = inherit System.Collections.Generic.List<InputEndpoint>()
    
type UpgradeType = Auto | Manual
with
    override x.ToString() = Reflection.unionToStringPlain x
    static member Parse(str) = Reflection.stringToUnionPlain<UpgradeType> str

type UpgradeDomainState = Before | During
with 
    override x.ToString() = Reflection.unionToStringPlain x
    static member Parse(str) = Reflection.stringToUnionPlain<UpgradeDomainState> str

[<DataContract(Name = "UpgradeStatus", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type UpgradeStatus() =
    let mutable ``type`` = Auto
    let mutable domainState = Before
    let mutable domainNumber = 0
    [<DataMember(Name = "UpgradeType", Order = 1)>]
    member private x.TypeStr 
        with get () = ``type``.ToString() and 
            set (v: string) = ``type`` <- UpgradeType.Parse  v
    member x.Type = ``type``
    [<DataMember(Name = "CurrentUpgradeDomainState", Order = 2)>]
    member private x.DomainStateStr 
        with get () = domainState.ToString() and 
            set (v: string) = domainState <- UpgradeDomainState.Parse(v)
    member x.DomainState = domainState
    [<DataMember(Name = "CurrentUpgradeDomain", Order = 3)>]
    member x.DomainNumber with get () = domainNumber and set v = domainNumber <- v

[<DataContract(Name = "RoleInstance", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type RoleInstance() =
    let mutable name = ""
    let mutable instanceName = ""
    let mutable status = Version2 RoleStateUnknown
    let mutable upgradeDomain = 0
    let mutable faultDomain = 0
    let mutable size = ExtraSmall
    let mutable stateDetails = ""
    let mutable errorCode = ""
    [<DataMember(Name = "RoleName", Order = 1)>]
    member x.Name with get () = name and set v = name <- v
    [<DataMember(Name = "InstanceName", Order = 2)>]
    member x.InstanceName with get () = instanceName and set v = instanceName <- v
    [<DataMember(Name = "InstanceStatus", Order = 3)>]
    member private x.StatusStr with get () = status.ToString() and set (v: string) = status <- InstanceStatus.Parse v
    member x.Status = status
    [<DataMember(Name = "InstanceUpgradeDomain", Order = 4, IsRequired = false)>]
    member x.UpgradeDomain with get () = upgradeDomain and set v = upgradeDomain <- v
    [<DataMember(Name = "InstanceFaultDomain", Order = 5, IsRequired = false)>]
    member x.FaultDomain with get () = faultDomain and set v = faultDomain <- v
    [<DataMember(Name = "InstanceSize", Order = 6, IsRequired = false)>]
    member private x.SizeStr with get () = size.ToString() and set (v: string) = size <- InstanceSize.Parse v
    member x.Size = size
    [<DataMember(Name = "InstanceStateDetails", Order = 7, IsRequired = false)>]
    member x.StateDetails with get () = stateDetails and set v = stateDetails <- v
    [<DataMember(Name = "InstanceErrorCode", Order = 8, IsRequired = false)>]
    member x.ErrorCode with get () = errorCode and set v = errorCode <- v

[<CollectionDataContract(Name = "RoleInstanceList", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type RoleInstances() = inherit System.Collections.Generic.List<RoleInstance>()

[<DataContract(Name = "Role", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type Role() =
    let mutable name = ""
    let mutable osVersion = ""
    [<DataMember(Name = "RoleName", Order = 1)>]
    member x.Name with get () = name and set v = name <- v
    [<DataMember(Name = "OsVersion", Order = 2)>]
    member x.OsVersion with get () = osVersion and set v = osVersion <- v
    
[<CollectionDataContract(Name = "RoleList", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type Roles() = inherit System.Collections.Generic.List<Role>()

[<DataContract(Name = "Deployment", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type Deployment() =
    let mutable name = ""
    let mutable slot = Staging
    let mutable id = ""
    let mutable status = Suspended
    let mutable label = ""
    let mutable url = ""
    let mutable config = ServiceConfiguration()
    let mutable roleInstances = RoleInstances()
    let mutable upgradeStatus = UpgradeStatus()
    let mutable uDomainCount = 0
    let mutable roles = Roles()
    let mutable sdkVersion = ""
    let mutable endpoints = InputEndpoints()
    let mutable isLocked = false
    let mutable isRollbackAllowed = true
    [<DataMember(Name = "Name", Order = 1)>]
    member x.Name with get () = name and set v = name <- v
    [<DataMember(Name = "DeploymentSlot", Order = 2)>]
    member private x.SlotStr 
        with get () = slot.ToString() and 
            set (v: string) = slot <- DeploymentSlot.Parse(v)
    member x.Slot = slot
    [<DataMember(Name = "PrivateID", Order = 3)>]
    member x.PrivateId with get () = id and set v = id <- v
    [<DataMember(Name = "Status", Order = 4)>]
    member private x.StatusStr with get () = status.ToString() and set (v: string) = status <- DeploymentStatus.Parse v
    member x.Status = status
    [<DataMember(Name = "Label", Order = 5)>]
    member private x.LabelEncoded with get () = label.ToBase64() and set (v: string) = label <- v.FromBase64()
    member x.Label with get () = label and set v = label <- v
    [<DataMember(Name = "Url", Order = 5)>]
    member x.Url with get () = url and set v = url <- v
    [<DataMember(Name = "Configuration", Order = 5)>]
    member private x.ConfigEncoded 
        with get () = config.ToString().ToBase64() and 
            set (v: string) = config <- ServiceConfiguration.LoadFromString(v.FromBase64())
    member x.Config = config
    [<DataMember(Name = "RoleInstanceList", Order = 6)>]
    member x.RoleInstances with get () = roleInstances and set v = roleInstances <- v
    [<DataMember(Name = "UpgradeStatus", Order = 7)>]
    member x.UpgradeStatus with get () = upgradeStatus and set v = upgradeStatus <- v
    [<DataMember(Name = "UpgradeDomainCount", Order = 8)>]
    member x.UpgradeDomainCount with get () = uDomainCount and set v = uDomainCount <- v
    [<DataMember(Name = "RoleList", Order = 9)>]
    member x.Roles with get () = roles and set v = roles <- v
    [<DataMember(Name = "SdkVersion", Order = 10, IsRequired = false)>]
    member x.SdkVersion with get () = sdkVersion and set v = sdkVersion <- v
    [<DataMember(Name = "InputEndpointList", Order = 11, IsRequired = false)>]
    member x.InputEndpoints with get () = endpoints and set v = endpoints <- v
    [<DataMember(Name = "Locked", Order = 12, IsRequired = false)>]
    member x.Locked with get () = isLocked and set v = isLocked <- v
    [<DataMember(Name = "RollbackAllowed", Order = 13, IsRequired = false)>]
    member x.RollbackAllowed with get () = isRollbackAllowed and set v = isRollbackAllowed <- v
    
(*
<?xml version="1.0" encoding="utf-8"?>
<ChangeConfiguration xmlns="http://schemas.microsoft.com/windowsazure">
   <Configuration>base-64-encoded-configuration-file</Configuration>
   <TreatWarningsAsError>true|false</TreatWarningsAsError>
   <Mode>Auto|Manual</Mode>
</ChangeConfiguration>
*)    

[<DataContract(Name = "ChangeConfiguration", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type ConfigurationChanging(treatWarnsAsError: bool, changeType: UpgradeType) =
    let mutable config = ServiceConfiguration()
    [<DataMember(Name = "Configuration", Order = 1)>]
    member private x.ConfigEncoded with get () = config.ToString().ToBase64() and set (v:string) = config <- ServiceConfiguration.LoadFromString(v.FromBase64())
    member x.Config with get () = config and set v = config <- v
    [<DataMember(Name = "TreatWarningsAsError", Order = 2)>]
    member private x.TreatWarnsAsErr with get () = treatWarnsAsError and set _ = ()
    [<DataMember(Name = "Mode", Order = 3)>]
    member private x.ModeStr with get () = changeType.ToString() and set _ = ()

(*
<?xml version="1.0" encoding="utf-8"?>
<UpgradeDeployment xmlns="http://schemas.microsoft.com/windowsazure">
   <Mode>auto|manual</Mode>
   <PackageUrl>url-to-package</PackageUrl>
   <Configuration>base64-encoded-config-file</Configuration>
   <Label>base-64-encoded-label</Label>
   <RoleToUpgrade>role-name</RoleToUpgrade>
   <Force>true|false</Force>
</UpgradeDeployment>
*)
[<DataContract(Name = "UpgradeDeployment", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type DeploymentGlobalUpgarde(mode: UpgradeType, force: bool) = 
    let mutable packageUrl = ""
    let mutable label = ""
    let mutable config = ServiceConfiguration()
    [<DataMember(Name = "Mode", Order = 1)>]
    member private x.ModeStr with get () = mode.ToString() and set _ = ()   
    [<DataMember(Name = "PackageUrl", Order = 2)>]
    member x.PackageUrl with get () = packageUrl and set v = packageUrl <- v
    [<DataMember(Name = "Configuration", Order = 3)>]
    member private x.ConfigEncoded with get () = config.ToString().ToBase64() and set (v:string) = config <- ServiceConfiguration.LoadFromString(v.FromBase64())
    member x.Config with get () = config and set v = config <- v
    [<DataMember(Name = "Label", Order = 4)>]
    member private x.LabelEncoded with get () = label and set v = label <- v
    member x.Label with get () = label.FromBase64() and set (v: string) = label <- v.ToBase64()
    [<DataMember(Name = "Force", Order = 6)>]
    member private x.Force with get () = force and set _ = ()

[<DataContract(Name = "UpgradeDeployment", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type DeploymentRoleUpgarde(roleName, mode, force) = 
    inherit DeploymentGlobalUpgarde(mode, force)
    [<DataMember(Name = "RoleToUpgrade", Order = 5)>]
    member x.RoleName with get () = roleName and set _ = ()

(*
<?xml version="1.0" encoding="utf-8"?>
<Swap xmlns="http://schemas.microsoft.com/windowsazure">
  <Production>production-deployment-name</Production>
  <SourceDeployment>deployment-name-to-be-swapped-with-production</SourceDeployment>
</Swap>
*)
[<DataContract(Name = "Swap", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type DeploymentSwap(deplName, sourceName) =
    [<DataMember(Name = "Production", Order = 1)>] 
    member private x.ProductionDeployment with get () = deplName and set _ = ()
    [<DataMember(Name = "SourceDeployment", Order = 2)>] 
    member private x.SourceDeployment with get () = sourceName and set _ = ()

(*
<?xml version="1.0" encoding="utf-8"?>
<UpdateDeploymentStatus xmlns="http://schemas.microsoft.com/windowsazure">
  <Status>Running|Suspended</Status>
</UpdateDeploymentStatus>
*)
[<DataContract(Name = "UpdateDeploymentStatus", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type DeploymentStatusUpdate(status: DeploymentStatus) =
    [<DataMember(Name = "Status", Order = 1)>]
    member private x.Status with get () = status.ToString() and set _ = ()

(*
<?xml version="1.0" encoding="utf-8"?>
<WalkUpgradeDomain xmlns="http://schemas.microsoft.com/windowsazure">
  <UpgradeDomain>upgrade-domain-id</UpgradeDomain>
</WalkUpgradeDomain>
*)
[<DataContract(Name = "WalkUpgradeDomain", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type UpgradeDomainWalk(id: int) = 
    [<DataMember(Name = "UpgradeDomain", Order = 1)>]
    member private x.Current with get() = id and set _ = ()
(*
<?xml version="1.0" encoding="utf-8"?>
<RollbackUpdateOrUpgrade xmlns=”http://schemas.microsoft.com/windowsazure”>
   <Mode>auto|manual</Mode>
   <Force>true|false</Force>
</RollbackUpdateOrUpgrade>
*)
[<DataContract(Name = "RollbackUpdateOrUpgrade", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type DeploymentRollback(mode: UpgradeType, force: bool) = 
    [<DataMember(Name = "Mode", Order = 1)>]
    member private x.ModeStr with get() = mode.ToString() and set _ = ()
    [<DataMember(Name = "Force", Order = 2)>]
    member private x.ForceStr with get () = force and set _ = ()
[<Interface>]
[<ServiceContractAttribute>]
type IDeploymentManagement =
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}", Method="POST")>]
    abstract CreateDeployment: serviceName:string * deploymentSlot:string * creation:DeploymentCreation -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginCreateDeployment: serviceName:string *deploymentSlot:string *creation: DeploymentCreation*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndCreateDeployment: result:IAsyncResult -> unit
    
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}", Method="GET")>]
    abstract GetDeploymentInSlot: serviceName:string * deploymentSlot:string -> Deployment
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginGetDeploymentInSlot: serviceName:string*deploymentSlot:string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndGetDeploymentInSlot: result:IAsyncResult -> Deployment

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}", Method="GET")>]
    abstract GetDeploymentByName: serviceName:string * deploymentName:string -> Deployment
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginGetDeploymentByName: serviceName:string *deploymentName:string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndGetDeploymentByName: result:IAsyncResult -> Deployment

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}", Method="DELETE")>]
    abstract DeleteDeploymentInSlot: serviceName:string * deploymentSlot:string -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginDeleteDeploymentInSlot: serviceName:string*deploymentSlot:string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndDeleteDeploymentInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}", Method="DELETE")>]
    abstract DeleteDeploymentByName: serviceName:string * deploymentName:string -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginDeleteDeploymentByName: serviceName:string *deploymentName:string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndDeleteDeploymentByName: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}", Method="POST")>]
    abstract SwapDeployments: serviceName:string*swap: DeploymentSwap -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginSwapDeployments: serviceName:string*swap: DeploymentSwap*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndSwapDeployments: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}/?comp=config", Method="POST")>]
    abstract ChangeDeploymentConfigurationInSlot: serviceName:string*deploymentSlot:string*configChanging:ConfigurationChanging -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginChangeDeploymentConfigurationInSlot: serviceName:string*deploymentSlot:string*configChanging:ConfigurationChanging*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndChangeDeploymentConfigurationInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}/?comp=config", Method="POST")>]
    abstract ChangeDeploymentConfigurationByName: serviceName:string*deploymentName:string*configChanging:ConfigurationChanging -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginChangeDeploymentConfigurationByName: serviceName:string*deploymentName:string*configChanging:ConfigurationChanging*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndChangeDeploymentConfigurationByName: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}/?comp=status", Method="POST")>]
    abstract UpdateDeploymentStatusInSlot: serviceName:string*deploymentSlot:string*statusUpdate:DeploymentStatusUpdate -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginUpdateDeploymentStatusInSlot: serviceName:string*deploymentSlot:string*statusUpdate:DeploymentStatusUpdate*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndUpdateDeploymentStatusInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}/?comp=status", Method="POST")>]
    abstract UpdateDeploymentStatusByName: serviceName:string*deploymentName:string*update:DeploymentStatusUpdate -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginUpdateDeploymentStatusByName: serviceName:string*deploymentName:string*update:DeploymentStatusUpdate*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndUpdateDeploymentStatusByName: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}/?comp=upgrade", Method="POST")>]
    abstract UpgradeAllDeploymentRolesInSlot: serviceName:string*deploymentSlot:string*upgrade:DeploymentGlobalUpgarde -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginUpgradeAllDeploymentRolesInSlot: serviceName:string*deploymentSlot:string*upgrade:DeploymentGlobalUpgarde*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndUpgradeAllDeploymentRolesInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}/?comp=upgrade", Method="POST")>]
    abstract UpgradeAllDeploymentRolesByName: serviceName:string*deploymentName:string*upgrade:DeploymentGlobalUpgarde -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginUpgradeAllDeploymentRolesByName: serviceName:string*deploymentName:string*upgrade:DeploymentGlobalUpgarde*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndUpgradeAllDeploymentRolesByName: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}/?comp=upgrade", Method="POST")>]
    abstract UpgradeDeploymentRoleInSlot: serviceName:string*deploymentSlot:string*upgrade:DeploymentRoleUpgarde -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginUpgradeDeploymentRoleInSlot: serviceName:string*deploymentSlot:string*upgrade:DeploymentRoleUpgarde*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndUpgradeDeploymentRoleInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}/?comp=upgrade", Method="POST")>]
    abstract UpgradeDeploymentRoleByName: serviceName:string*deploymentName:string*upgrade:DeploymentRoleUpgarde -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginUpgradeDeploymentRoleByName: serviceName:string*deploymentName:string*upgrade:DeploymentRoleUpgarde*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndUpgradeDeploymentRoleByName: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}/?comp=walkupgradedomain", Method="POST")>]
    abstract WalkUpgradeDomainInSlot: serviceName:string*deploymentSlot:string*walk:UpgradeDomainWalk -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginWalkUpgradeDomainInSlot: serviceName:string*deploymentSlot:string*walk:UpgradeDomainWalk*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndWalkUpgradeDomainInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}/?comp=walkupgradedomain", Method="POST")>]
    abstract WalkUpgradeDomainByName: serviceName:string*deploymentName:string*walk:UpgradeDomainWalk -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginWalkUpgradeDomainByName: serviceName:string*deploymentName:string*walk:UpgradeDomainWalk*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndWalkUpgradeDomainByName: result:IAsyncResult -> unit

    // TODO: ContentLength = 0
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}/roleinstances/{roleInstanceName}?comp=reboot", Method="POST")>]
    abstract RebootDeploymentRoleInstanceInSlot: serviceName:string*deploymentSlot:string*roleInstanceName: string -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginRebootDeploymentRoleInstanceInSlot: serviceName:string*deploymentSlot:string*roleInstanceName: string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndRebootDeploymentRoleInstanceInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}/roleinstances/{roleInstanceName}?comp=reboot", Method="POST")>]
    abstract RebootDeploymentRoleInstanceByName: serviceName:string*deploymentName:string*roleInstanceName: string -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginRebootDeploymentRoleInstanceByName: serviceName:string*deploymentName:string*roleInstanceName: string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndRebootDeploymentRoleInstanceByName: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}/roleinstances/{roleInstanceName}?comp=reimage", Method="POST")>]
    abstract ReimageDeploymentRoleInstanceInSlot: serviceName:string*deploymentSlot:string*roleInstanceName: string -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginReimageDeploymentRoleInstanceInSlot: serviceName:string*deploymentSlot:string*roleInstanceName: string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndReimageDeploymentRoleInstanceInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}/roleinstances/{roleInstanceName}?comp=reimage", Method="POST")>]
    abstract ReimageDeploymentRoleInstanceByName: serviceName:string*deploymentName:string*roleInstanceName: string -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginReimageDeploymentRoleInstanceByName: serviceName:string*deploymentName:string*roleInstanceName: string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndReimageDeploymentRoleInstanceByName: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlot}/?comp=rollback", Method="POST")>]
    abstract RollbackDeploymentUpgradeInSlot: serviceName:string*deploymentSlot:string*rollback:DeploymentRollback -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginRollbackDeploymentUpgradeInSlot: serviceName:string*deploymentSlot:string*rollback:DeploymentRollback*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndRollbackDeploymentUpgradeInSlot: result:IAsyncResult -> unit

    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}/deployments/{deploymentName}/?comp=rollback", Method="POST")>]
    abstract RollbackDeploymentUpgradeByName: serviceName:string*deploymentName:string*rollback:DeploymentRollback -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginRollbackDeploymentUpgradeByName: serviceName:string*deploymentName:string*rollback:DeploymentRollback*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndRollbackDeploymentUpgradeByName: result:IAsyncResult -> unit